package com.ly.consumer.thread.threadCommunication;

import com.common.core.utils.ThreadPoolUtil;

import java.util.concurrent.ThreadPoolExecutor;

//线程之间的通信  等待唤醒机制
//例子：模拟顾客去早餐店买早餐
//使用runnable方式实现线程
//顾客
class Customer1 implements Runnable{
    private Object lock;
    public Customer1(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        //使用wait方法让顾客线程释放掉锁,被唤醒之后继续去竞争所资源
        synchronized (lock){
            //顾客点餐
            System.out.println("顾客1：1.顾客点餐：我需要2个包子和一个豆浆");
            try {
//                lock.wait();//释放锁  在等待池中 程序不会继续往下走
                lock.wait(2000);//释放锁  指定时间后继续执行
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //拿到了锁 拿到了cpu的使用权 继续往下执行
            //顾客吃饭
            System.out.println("顾客1：3.顾客吃上了");
        }
    }
}
class Customer2 implements Runnable{
    private Object lock;
    public Customer2(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        //使用wait方法让顾客线程释放掉锁,被唤醒之后继续去竞争所资源
        synchronized (lock){
            //顾客点餐
            System.out.println("顾客2：1.顾客点餐：我需要2个包子和一个豆浆");
            try {
                lock.wait();//释放锁  在等待池中 程序不会继续往下走
//                lock.wait(2000);//释放锁  指定时间后继续执行
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //拿到了锁 拿到了cpu的使用权 继续往下执行
            //顾客吃饭
            System.out.println("顾客2：3.顾客吃上了");
        }
    }
}

//老板
class Boss implements Runnable{
    private Object lock;
    public Boss(Object lock) {
        this.lock = lock;
    }
    @Override
    public void run() {
        synchronized (lock){//拿到了这把锁
            try {
                //等待两秒 模拟老板出餐
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //通知 synchronized{} 代码块会执行结束释放锁
            //使用notify方法来唤醒顾客线程的锁 只能唤醒一个
            lock.notify();
//            lock.notifyAll();//唤醒多个
            //老板出餐完成通知顾客来取
            System.out.println("2.老板出餐完成！");
        }//释放掉锁资源
    }
}
public class MyThreadCommunication {
    //必须是同一把锁因此声明个相同的全局对象
    private static Object lock = new Object ();
    public static void main(String[] args) {
//        //顾客线程
//        Thread customer1 = new Thread(new Customer1(lock));
//        customer1.start();
//        Thread customer2 = new Thread(new Customer2(lock));
//        customer2.start();
//        //老板线程
//        Thread boss = new Thread(new Boss(lock));
//        boss.start();
        //使用线程池来实现
        //必须是同一把锁
        ThreadPoolExecutor threadPoolExecutor =ThreadPoolUtil.getThreadPoolExecutorCPU();
        Customer1 customer1 = new Customer1(lock);
        Customer2 customer2 = new Customer2(lock);
        Boss boss = new Boss(lock);
        threadPoolExecutor.submit(customer1);
        threadPoolExecutor.submit(customer2);
        threadPoolExecutor.submit(boss);
    }
}
